/*
 * @Author: ereddate
 * @Date: 2022-12-12 16:40:34
 * @LastEditors: yandong 18900360@qq.com
 * @LastEditTime: 2023-01-16 14:41:52
 * @FilePath: \mfox\mfox.window.js
 * @Description: update
 */
"use strict";
((global, factory) => {
  typeof exports === "object" && typeof module !== "undefined"
    ? (module.exports = factory(global))
    : typeof define === "function" && define.amd
    ? define(() => factory(global))
    : ((global =
        typeof globalThis !== "undefined" ? globalThis : global || self),
      (global.mfox = factory(global)));
})(window, (global) => {
  const oForEach = function (target, callback) {
    Object.keys(target).forEach(
      (n) =>
        !/oForEach|oFilter/.test(n) &&
        callback.call(target, target[n], n, target)
    );
    return target;
  };
  const oFilter = function (target, callback) {
    let _target = {};
    Object.keys(target).forEach((n) => {
      const res = callback.call(target, target[n], n, target);
      if (res) {
        _target[n] = target[n];
      }
    });
    return _target;
  };
  const DEFAULT_STORENAME = "BASEDATASTORE";
  const DEFAULT_STATE = ["state", "actions", "mutations", "getters"];
  class LocalStorge {
    constructor(options) {
      if (options) {
        switch (options.mode) {
          /* case "large":
            this.store = new LocalIndexedDB(options);
            break;
          case "small":
            this.store = new LocalCookie(options);
            break; */
          default:
            if (options.staging) {
              this.store = global.sessionStorage;
            } else {
              this.store = global.localStorage;
            }
            break;
        }

        if (options && options.storeName) {
          this.dataStoreName = options.storeName;
        } else {
          this.dataStoreName = DEFAULT_STORENAME;
        }
        this.store.setItem(
          this.dataStoreName,
          JSON.stringify({ data: options.data || {} })
        );
        logs.push({
          type: "LocalStorge create",
          args: { options: JSON.stringify(options) },
          time: new Date().getTime(),
        });
      }
      return this;
    }
    dataStoreName = "";
    parent = null;
    get(name) {
      logs.push({
        type: "LocalStorge set",
        args: { name },
        time: new Date().getTime(),
      });
      let res = this.store.getItem(this.dataStoreName);
      if (res) {
        res = JSON.parse(res);
        if (name) {
          return res.data[name];
        }
        return res.data;
      } else {
        return;
      }
    }
    set(name, value) {
      logs.push({
        type: "LocalStorge set",
        args: { name, value: JSON.stringify(value) },
        time: new Date().getTime(),
      });
      let res = this.store.getItem(this.dataStoreName);
      if (res) {
        res = JSON.parse(res);
        if (name && value) {
          res.data[name] = value;
          this.store.setItem(this.dataStoreName, JSON.stringify(res));
        }
        return this;
      } else {
        return;
      }
    }
    update(data) {
      logs.push({
        type: "LocalStorge update",
        args: { data: JSON.stringify(data) },
        time: new Date().getTime(),
      });
      let res = this.store.getItem(this.dataStoreName);
      if (res) {
        res = JSON.parse(res);
        res.data = Object.assign(res.data, data);
        this.store.setItem(this.dataStoreName, JSON.stringify(res));
        return this;
      } else {
        return;
      }
    }
    remove(name) {
      logs.push({
        type: "LocalStorge remove",
        args: { name },
        time: new Date().getTime(),
      });
      let res = this.store.getItem(this.dataStoreName);
      if (res) {
        res = JSON.parse(res);
        delete res.data[name];
        this.store.setItem(this.dataStoreName, JSON.stringify(res));
        return this;
      } else {
        return;
      }
    }
    clear() {
      logs.push({
        type: "LocalStorge clear",
        time: new Date().getTime(),
      });
      let res = this.store.getItem(this.dataStoreName);
      if (res) {
        this.store.setItem(this.dataStoreName, JSON.stringify({ data: {} }));
        return this;
      } else {
        return;
      }
    }
  }

  const isEmptyObject = function (obj) {
    for (var name in obj) {
      return false;
    }
    return true;
  };
  const isRegExp = function (obj) {
    let bool = typeof obj === "object" && typeof obj.test === "function";
    return bool;
  };

  /* class ModuleColline {
    constructor(ops) {
      if (ops) {
        this.createModule(ops);
      }
      return this;
    }
    createModule(ops) {
      const { name } = ops;
      const res = this.has(name);
      if (res.length > 0) {
        this.update(res[0], ops);
        return res[0];
      }
      const currentTime = new Date().getTime();
      const newModule = new Modules(
        Object.assign(ops, {
          createTime: currentTime,
          editTime: currentTime,
          index: this.length + 1,
        })
      );
      this.add(newModule);
      this.update(newModule, ops);
      return newModule;
    }
    add(module) {
      this.modules.push(module);
      this.length = this.modules.length;
      return this;
    }
    update(module, ops) {
      resetStore(module, ops);
      resetStoreState(module, ops.state);
      return this;
    }
    delete(name) {
      let currentModuleIndex = -1;
      const res = this.modules.filter(
        (item, index) => item.name === name && (currentModuleIndex = index)
      );
      res.length > 0 &&
        currentModuleIndex >= 0 &&
        this.modules.splice(currentModuleIndex, 1),
        (this.length = this.modules.length);
      return this;
    }
    has(name) {
      const res = this.modules.filter((item) => item.name === name);
      return res.length > 0 ? res : false;
    }
    length = 0;
    modules = [];
  }
 */
  class Modules {
    constructor(ops) {
      const that = this;
      if (ops) {
        this.name = ops.name;
        this.store = ops.store;
        this.index = ops.index || -1;
        this.createTime = ops.createTime || new Date().getTime();
        this.editTime = ops.editTime || new Date().getTime();
        this.parentObj = ops.parentObj;
        this.namespaced = ops.namespaced;
      }
      logs.push({
        type: "Modules create",
        args: { ops },
        time: new Date().getTime(),
      });
      return this;
    }
    get state() {
      logs.push({
        type: "Modules get state",
        time: new Date().getTime(),
      });
      return this._state;
    }
    set state(ops) {
      const that = this;
      if (ops) {
        this._state = ops;
        this.store.update(this._state);

        logs.push({
          type: "Modules set state",
          args: { ops: JSON.stringify(ops) },
          time: new Date().getTime(),
        });

        oForEach(this._getters, (value, name) => {
          typeof that._getters[name].fn === "function" &&
            (that._getters[name].value = that._getters[name].fn.call(
              that.parentObj,
              that.state
            ));
        });
      }
      return this;
    }
    get getters() {
      let getters = {};
      oForEach(this._getters, (value, name) => {
        getters[name] = value.value;
      });
      return getters;
    }
    set getters(ops) {
      let getters = {};
      oForEach(ops, (value, name) => {
        getters[name] = {
          value: getters[name] ? getters[name].value : null,
          fn: value,
        };
      });
      this._getters = getters;
      logs.push({
        type: "Modules set getters",
        args: { ops: JSON.stringify(ops) },
        time: new Date().getTime(),
      });
      return this;
    }
    get actions() {
      return this._actions;
    }
    set actions(ops) {
      this._actions = ops;
      logs.push({
        type: "Modules set actions",
        args: { ops: JSON.stringify(ops) },
        time: new Date().getTime(),
      });
      return this;
    }
    get mutations() {
      return this._mutations;
    }
    set mutations(ops) {
      this._mutations = ops;
      logs.push({
        type: "Modules set mutations",
        args: { ops: JSON.stringify(ops) },
        time: new Date().getTime(),
      });
      return this;
    }
    namespaced = false;
    parentObj = Object.create(null);
    index = -1;
    _state = {};
    _actions = {};
    _mutations = {};
    _getters = {};
    createTime = new Date().getTime();
    editTime = new Date().getTime();
  }

  class SubscribeType {
    controller(ops) {
      return this;
    }
    options = Object.create(null);
    after = (res) => Promise.resolve(res);
    before = (res) => Promise.resolve(res);
    error = (res) => Promise.resolve(res);
  }
  class SubscribeGetterType {
    controller(ops) {
      return this;
    }
    options = Object.create(null);
    after = (res) => {
      return res;
    };
    before = (res) => {
      return res;
    };
    error = (res) => {
      return res;
    };
  }

  const loadSingleModule = (url) => {
    return new Promise((resolve, reject) => {
      const head = global.document.querySelector("head"),
        script = global.document.createElement("script");
      script.src = url;
      head.appendChild(script);
      script.onload = script.onerror = function () {
        logs.push({
          type: "loadSingleModule",
          args: { url },
          time: new Date().getTime(),
        });
        resolve();
      };
    });
  };

  let tempModules = {};
  global.moduleConfig = (name, factory) => {
    tempModules[name] = factory();
  };

  const loadModule = (depends, baseOps, callback) => {
    let promiseItems = [];
    depends.forEach((item) =>
      promiseItems.push(
        loadSingleModule(
          [
            baseOps.base,
            "/",
            item,
            baseOps.ext,
            //"?t=" + new Date().getTime(),
          ].join("")
        )
      )
    );
    return Promise.all(promiseItems).then(() => {
      return Promise.resolve(tempModules);
    });
  };

  let localModules = [];
  let logs = [];

  const resetStore = (module, updateModule) => {
    if (updateModule && !isEmptyObject(updateModule)) {
      DEFAULT_STATE.filter((item) => item !== "state").forEach((name) => {
        updateModule[name] &&
          module[name] &&
          (module[name] = updateModule[name] || {});
      });
      module.editTime = new Date().getTime();
    }
  };

  const resetStoreState = (module, state, target) => {
    if (state && !isEmptyObject(state)) {
      module.state = { ...state }; //Object.assign({ ...module.state }, { ...state });
      /* oForEach(module._getters, (value, name) => {
        const computedCache = target.computed(name, module);
        Object.defineProperty(module._getters, name, {
          get: () => {
            return { value: computedCache, fn: value.fn };
          },
          enumerable: true, // for local getters
        });
      }); */
      module.editTime = new Date().getTime();
    }
  };

  const resetCurrentModule = (target, res) => {
    target.currentModule = res[0];
    target.currentModuleName = res[0].name;
    target.currentModuleIndex = res[0].index;
    const { store } = target.currentModule;
    target.store = store;
  };

  const subscribe = function () {
    const args = arguments;
    const that = this;
    const importType = args.length === 2 ? args[1] : args[2];
    const type =
      importType === "subscribe"
        ? "_subscribe"
        : importType === "sucscribeAction"
        ? "_subscribeAction"
        : "_subscribeGetter";
    if (args.length === 2) {
      Object.keys(args[0]).forEach((n) => {
        switch (n) {
          case "before":
          case "after":
          case "error":
            that[type][n] = (res) => {
              if (typeof args[0][n] === "function") {
                args[0][n].call(
                  that,
                  type !== "_subscribeGetter"
                    ? { type: res, store: that }
                    : res,
                  that.currentModule.state
                );
              }
              return type === "_subscribeGetter" ? res : Promise.resolve(res);
            };
            break;
          case "options":
            that[type].options = Object.assign(
              that.currentModule[type].options,
              args[0][n]
            );
            break;
        }
      });
    } else if (args.length === 3) {
      this[type].options = Object.assign(this[type].options, args[1]);
      const appendType = args[1].prepend ? "before" : "after";
      this[type][appendType] = (res) => {
        if (typeof args[0] === "function") {
          args[0].call(
            that,
            type !== "_subscribeGetter" ? { type: res, store: that } : res,
            that.currentModule.state
          );
        }
        return type === "_subscribeGetter" ? res : Promise.resolve(res);
      };
    }
  };

  const getNamespace = (path, module) => {
    return path.reduce((namespace, key) => {
      module = module.filter((item) => item.name === key);
      return namespace + (module[0].namespaced ? key + "/" : "");
    }, "");
  };

  const upperFirst = (str) => {
    str = str.toLowerCase();
    str = str.substr(0, 1).toUpperCase() + str.substr(1, str.length - 1);
    return str;
  };

  class Computer {
    constructor(ops) {
      this.store = ops.store;
      return this;
    }
    computed() {
      const args = arguments;
      const target = this.store;
      const that = this;
      try {
        const getters = (args[1] || target.currentModule)._getters[args[0]];
        if (getters) {
          let res = that.before(getters.value);
          res =
            res ||
            (getters.fn &&
              getters.fn.call(
                args[1] || target,
                (args[1] && args[1].state) || target.state,
                res
              ));
          that.after(res);
          getters.value = res;
          return res;
        } else {
          return;
        }
      } catch (err) {
        return that.error(err);
      }
    }
    before(res) {
      const that = this.store;
      return that._subscribeGetter.before(res);
    }
    after(res) {
      const that = this.store;
      return that._subscribeGetter.after(res);
    }
    error(err) {
      const that = this.store;
      return that._subscribeGetter.error(err);
    }
  }

  class Commiter {
    constructor(ops) {
      this.store = ops.store;
      return this;
    }
    commit() {
      const args = arguments;
      const target = this.store;
      const that = this;
      return new Promise((resolve, reject) => {
        if (args[0]) {
          try {
            that
              .before(args[0])
              .then((res) => {
                return new Promise((resolve, reject) => {
                  const result = target.currentModule.mutations[args[0]].call(
                    target,
                    target.state,
                    args[1]
                  );
                  resolve(result);
                });
              })
              .then((res) => {
                return that.after(args[0]);
              })
              .then((res) => resolve(res));
          } catch (err) {
            that.error(err).then((err) => reject(err));
          }
        } else {
          reject();
        }
      });
    }
    before(res) {
      const that = this.store;
      return that._subscribe.before(res);
    }
    after(res) {
      const that = this.store;
      return that._subscribe.after(res);
    }
    error(err) {
      const that = this.store;
      return that._subscribe.error(err);
    }
  }

  class Dispatcher {
    constructor(ops) {
      this.store = ops.store;
      return this;
    }
    dispatch() {
      const args = arguments;
      const target = this.store;
      const that = this;
      return new Promise((resolve, reject) => {
        if (args[0]) {
          try {
            that
              .before(args[0])
              .then((res) => {
                return new Promise((resolve, reject) => {
                  const result = target.currentModule.actions[args[0]].call(
                    target,
                    target,
                    args[1]
                  );
                  resolve(result);
                });
              })
              .then((res) => {
                return that.after(args[0]);
              })
              .then((res) => resolve(res));
          } catch (err) {
            that.error(err).then((err) => reject(err));
          }
        } else {
          reject();
        }
      });
    }
    before(res) {
      const that = this.store;
      return that._subscribeAction.before(res);
    }
    after(res) {
      const that = this.store;
      return that._subscribeAction.after(res);
    }
    error(err) {
      const that = this.store;
      return that._subscribeAction.error(err);
    }
  }

  class Store {
    constructor(ops) {
      this.configStore(ops);
      return this;
    }
    version = "0.0.7";
    strict = false;
    _subscribe = new SubscribeType();
    _subscribeAction = new SubscribeType();
    _subscribeGetter = new SubscribeGetterType();
    _namespaceMap = Object.create(null);
    get logs() {
      return logs;
    }
    get modules() {
      logs.push({
        type: "get modules",
        args: { module: this.currentModuleName },
        time: new Date().getTime(),
      });
      return localModules;
    }
    set modules(value) {
      localModules = value;
      logs.push({
        type: "set modules",
        args: {
          args: { value: JSON.stringify(value) },
          module: this.currentModuleName,
        },
        time: new Date().getTime(),
      });
      return this;
    }
    get state() {
      logs.push({
        type: "get state",
        args: { module: this.currentModuleName },
        time: new Date().getTime(),
      });
      return this.currentModule.state;
    }
    set state(ops) {
      if (typeof ops === "function") {
        ops = ops.call(this);
      }
      if (ops && !isEmptyObject(ops)) {
        this.currentModule.state = ops;
        this.currentModule.editTime = new Date().getTime();

        logs.push({
          type: "set state",
          args: {
            args: { ops: JSON.stringify(ops) },
            module: this.currentModuleName,
          },
          time: new Date().getTime(),
        });
      }
      return this;
    }
    setState(name, value) {
      this.currentModule.state = Object.assign(this.currentModule.state, {
        [name]: value,
      });
      logs.push({
        type: "setState",
        args: {
          module: this.currentModuleName,
          args: { name, value: JSON.stringify(value) },
        },
        time: new Date().getTime(),
      });
      return this;
    }
    replaceState(state) {
      this.currentModule.state = state;
      logs.push({
        type: "replaceState",
        args: {
          module: this.currentModuleName,
          args: { state },
        },
        time: new Date().getTime(),
      });
      return this;
    }
    configStore(ops) {
      const that = this;

      if (ops) {
        if (typeof ops === "function") {
          ops = ops.call(this);
        }

        const storeName = ops.currentModule || DEFAULT_STORENAME;
        this.strict = ops.strict || false;

        if (ops.modules) {
          oForEach(ops.modules, (value, name) =>
            that.registerModule(name, value)
          );
        } else {
          this.registerModule(storeName, ops);
        }

        const res = this.hasModule(storeName);
        if (res.length > 0) {
          resetCurrentModule(this, res);

          let _state = that.store.get();
          if (!isEmptyObject(_state)) {
            this.currentModule.state = Object.assign(
              that.currentModule.state,
              _state
            );
          }
        }
      }
      logs.push({
        type: "configStore",
        args: {
          module: this.currentModuleName,
          args: { ops: JSON.stringify(ops) },
        },
        time: new Date().getTime(),
      });
      return this;
    }
    registerModule(name, ops) {
      const res = this.hasModule(name);
      if (res.length > 0) {
        return res[0];
      }
      if (typeof ops === "function") {
        ops = ops.call(this);
      }
      const { staging, storeName, mode } = ops;

      const store = new LocalStorge({
        staging,
        storeName: storeName || name,
        mode,
      });
      const currentTime = new Date().getTime();
      const newModule = new Modules({
        store,
        name,
        index: this.modules.length + 1,
        createTime: currentTime,
        editTime: currentTime,
        parentObj: this,
        namespaced: ops.namespaced || false,
      });
      this.modules.push(newModule);
      store.parent = newModule;
      resetStore(newModule, ops);
      resetStoreState(newModule, ops.state, this);
      const namespace = getNamespace([name], this.modules);
      if (ops.namespaced) {
        const { _state, _mutations, _actions, _getters } = newModule;
        let childs = {};
        oForEach({ _state, _mutations, _actions, _getters }, (value, name) => {
          oForEach(value, (sv, n) => {
            childs[[name.replace("_", ""), n.replace("_", "")].join("/")] = sv;
          });
        });
        this._namespaceMap[namespace] = {
          childs,
          root: newModule,
        };
      }

      logs.push({
        type: "registerModule",
        args: {
          module: newModule.name,
          args: { name, ops: JSON.stringify(ops) },
        },
        time: new Date().getTime(),
      });
      return newModule;
    }
    switchModule(name) {
      const res = this.hasModule(name);
      if (res.length > 0) resetCurrentModule(this, res);
      logs.push({
        type: "switchModule",
        args: { module: this.currentModuleName, args: { name } },
        time: new Date().getTime(),
      });
      return this;
    }
    hotUpdate(ops) {
      const that = this;
      if (typeof ops === "function") {
        ops = ops.call(this);
      }
      if (ops && ops.modules) {
        oForEach(ops.modules, (value, name) => {
          const res = that.hasModule(name);
          if (res.length > 0) {
            let module = res[0];
            const updateModule = value;
            resetStore(module, updateModule);
            resetStoreState(module, updateModule.state, that);
          }
        });
      }
      logs.push({
        type: "hotUpdate",
        args: {
          module: this.currentModuleName,
          args: { ops: JSON.stringify(ops) },
        },
        time: new Date().getTime(),
      });
      return this;
    }
    cloneModule(from, to, bool) {
      if (from === to) return;
      const res = this.hasModule(from);
      if (res.length > 0) {
        const fromModule = res[0];
        const store = new LocalStorge({
          staging: fromModule.store.staging,
          storeName: to,
        });
        const currentTime = new Date().getTime();
        const toModule = new Modules({
          store,
          name: to,
          index: this.modules.length + 1,
          createTime: currentTime,
          editTime: currentTime,
        });
        oForEach(fromModule, (value, name) => {
          !/store|name|index|createTime|editTime/.test(name) &&
            (!bool
              ? !/state/.test(name) && (toModule[name] = { ...value })
              : (toModule[name] = { ...value }));
        });
        toModule.store.update(toModule.state);
        store.parent = toModule;
        this.modules.push(toModule);
      }
      logs.push({
        type: "cloneModule",
        args: {
          module: this.currentModuleName,
          args: { from, to, bool },
        },
        time: new Date().getTime(),
      });
      return this;
    }
    hasModule(name) {
      const res = this.modules.filter((item) => item.name === name);
      logs.push({
        type: "hasModule",
        args: {
          module: this.currentModuleName,
          args: { name },
        },
        time: new Date().getTime(),
      });
      return res.length > 0 ? res : false;
    }
    unregisterModule(name) {
      const res = this.hasModule(name);
      if (res.length > 0) {
        this.destroy(name);
      }
      logs.push({
        type: "unregisterModule",
        args: {
          module: this.currentModuleName,
          args: {
            name,
          },
        },
        time: new Date().getTime(),
      });
      return this;
    }
    queryState(filter, target) {
      target = target || this.currentModule.state;
      if (!filter) return;
      let filterResult = {};
      oForEach(target, (value, name) => {
        if (typeof filter === "function") {
          let res = filter(value, name);
          if (res) {
            filterResult = Object.assign(filterResult, { [name]: value });
          }
        } else if (isRegExp(filter) && filter.test(value)) {
          filterResult = Object.assign(filterResult, { [name]: value });
        } else if (value === filter) {
          filterResult = Object.assign(filterResult, { [name]: value });
        }
      });
      logs.push({
        type: "query",
        args: {
          module: this.currentModuleName,
          args: {
            filter: JSON.stringify(filter),
            target: JSON.stringify(target),
          },
        },
        time: new Date().getTime(),
      });
      return filterResult;
    }
    destroy(storeName) {
      const that = this;
      const oldModule = this.currentModule;
      const name = storeName || that.currentModuleName;
      let currentModuleIndex = -1;
      const res = this.modules.filter(
        (item, index) => item.name === name && (currentModuleIndex = index)
      );
      res.length > 0 &&
        currentModuleIndex >= 0 &&
        (this.modules.splice(currentModuleIndex, 1),
        this.store.store.removeItem(name));
      if (this.modules[0] && !storeName) {
        resetCurrentModule(this, this.modules);
      }
      logs.push({
        type: "destroy",
        args: {
          module: oldModule,
        },
        time: new Date().getTime(),
      });
      return this;
    }
    computed() {
      let args = arguments;
      logs.push({
        type: "computed",
        args: {
          module: this.currentModuleName,
          args: {
            args: [...arguments],
          },
        },
        time: new Date().getTime(),
      });

      const computer = new Computer({ store: this });
      return computer.computed(args[0], args[1]);
    }
    dispatch() {
      let args = arguments,
        that = this;

      logs.push({
        type: "dispatch",
        args: {
          module: this.currentModuleName,
          args: {
            args: [...arguments],
          },
        },
        time: new Date().getTime(),
      });

      const dispatcher = new Dispatcher({ store: that });
      return dispatcher.dispatch(args[0], args[1]);
    }
    commit() {
      let args = arguments,
        that = this;

      logs.push({
        type: "commit",
        args: {
          module: this.currentModuleName,
          args: {
            args: [...arguments],
          },
        },
        time: new Date().getTime(),
      });

      const commiter = new Commiter({ store: that });
      return commiter.commit(args[0], args[1]);
    }
    subscribe() {
      const args = arguments;
      logs.push({
        type: "subscribe",
        args: {
          module: this.currentModuleName,
          args: {
            args: [...arguments],
          },
        },
        time: new Date().getTime(),
      });

      subscribe.apply(this, [...args, "subscribe"]);
      return this;
    }
    subscribeAction() {
      const args = arguments;
      logs.push({
        type: "subscribeAction",
        args: {
          module: this.currentModuleName,
          args: {
            args: [...arguments],
          },
        },
        time: new Date().getTime(),
      });

      subscribe.apply(this, [...args, "subscribeAction"]);
      return this;
    }
    subscribeGetter() {
      const args = arguments;
      logs.push({
        type: "subscribeGetter",
        args: {
          module: this.currentModuleName,
          args: {
            args: [...arguments],
          },
        },
        time: new Date().getTime(),
      });

      subscribe.apply(this, [...args, "subscribeGetter"]);
      return this;
    }
    extend(a, b) {
      b = b || this;
      for (let n in a) b[n] = a[n];
      return b;
    }
  }

  DEFAULT_STATE.forEach(
    (item) =>
      (Store.prototype["map" + upperFirst(item)] = function () {
        const that = this;

        logs.push({
          type: "map" + upperFirst(item),
          args: {
            module: this.currentModuleName,
            args: {
              args: [...arguments],
            },
          },
          time: new Date().getTime(),
        });

        let map =
            arguments.length === 1 && Array.isArray(arguments[0])
              ? arguments[0]
              : [...arguments],
          mapObj = {};

        map.forEach((name) => {
          const namespace = name.split("/");
          if (namespace.length > 1) {
            const namespaceModule = that._namespaceMap[namespace[0] + "/"];
            namespace.splice(0, 1);
            const action = namespace.join("/");
            if (namespaceModule && namespaceModule.childs[action]) {
              let objName = action.split("/");
              objName = objName[objName.length - 1];
              mapObj = Object.assign(mapObj, {
                [objName]:
                  typeof namespaceModule.childs[action] === "function"
                    ? function (v) {
                        namespaceModule.childs[action].call(
                          that,
                          /getters|mutations/.test(item) ? that.state : that,
                          v
                        );
                      }
                    : namespaceModule.childs[action],
              });
            }
          } else {
            const res = that.currentModule[item][name];
            res &&
              (mapObj = Object.assign(mapObj, {
                [name]:
                  typeof res === "function"
                    ? function (v) {
                        res.call(
                          that,
                          /getters|mutations/.test(item) ? that.state : that,
                          v
                        );
                      }
                    : res,
              }));
          }
        });

        logs.push({
          type: "map" + upperFirst(item),
          args: {
            module: that.currentModuleName,
            args: {
              args: [...arguments],
            },
          },
          time: new Date().getTime(),
        });

        return mapObj;
      })
  );

  return {
    createStore(ops) {
      return new Store(ops);
    },
    Store,
    loadModule,
    use(factory) {
      oForEach(
        typeof factory === "function" ? factory() : factory,
        (value, name) => {
          Store.prototype[name] = value;
        }
      );
      return this;
    },
  };
});
